﻿Eg.Image = Eg.Class.extend({
  data: null,
  width: 0,
  height: 0,
  loaded: false,
  failed: false,
  path: '',
  loadCallback: null,
  init: function (path) {
    this.path = path;
  },
  load: function (loadCallback) {
    if (this.loaded) {
      if (loadCallback) {
        loadCallback(this.path, true);
      }
      return;
    }
    else if (!this.loaded && Eg.ready) {
      this.loadCallback = loadCallback || null;
      this.data = new Image();
      this.data.onload = this.onload.bind(this);
      this.data.onerror = this.onerror.bind(this);
      this.data.src = this.path;
    }
    else {
      Eg.addResource(this);
    }
    Eg.Image.cache[this.path] = this;
  },

  reload: function () {
    this.loaded = false;
    this.data = new Image();
    this.data.onload = this.onload.bind(this);
    this.data.src = this.path + '?' + Date.now();
  },


  onload: function (event) {
    this.width = this.data.width;
    this.height = this.data.height;
    if (Eg.sys.scale != 1) {
      this.resize(Eg.sys.scale);
    }
    this.loaded = true;
    if (this.loadCallback) {
      this.loadCallback(this.path, true);
    }
  },


  onerror: function (event) {
    this.failed = true;

    if (this.loadCallback) {
      this.loadCallback(this.path, false);
    }
  },

  resize: function (scale) {
    // Nearest-Neighbor scaling

    // The original image is drawn into an offscreen canvas of the same size
    // and copied into another offscreen canvas with the new size. 
    // The scaled offscreen canvas becomes the image (data) of this object.

    var widthScaled = this.width * scale;
    var heightScaled = this.height * scale;

    var orig = Eg.$new('canvas');
    orig.width = this.width;
    orig.height = this.height;
    var origCtx = orig.getContext('2d');
    origCtx.drawImage(this.data, 0, 0, this.width, this.height, 0, 0, this.width, this.height);
    var origPixels = origCtx.getImageData(0, 0, this.width, this.height);

    var scaled = Eg.$new('canvas');
    scaled.width = widthScaled;
    scaled.height = heightScaled;
    var scaledCtx = scaled.getContext('2d');
    var scaledPixels = scaledCtx.getImageData(0, 0, widthScaled, heightScaled);

    for (var y = 0; y < heightScaled; y++) {
      for (var x = 0; x < widthScaled; x++) {
        var index = (Math.floor(y / scale) * this.width + Math.floor(x / scale)) * 4;
        var indexScaled = (y * widthScaled + x) * 4;
        scaledPixels.data[indexScaled] = origPixels.data[index];
        scaledPixels.data[indexScaled + 1] = origPixels.data[index + 1];
        scaledPixels.data[indexScaled + 2] = origPixels.data[index + 2];
        scaledPixels.data[indexScaled + 3] = origPixels.data[index + 3];
      }
    }
    scaledCtx.putImageData(scaledPixels, 0, 0);
    this.data = scaled;
  },


  draw: function (targetX, targetY, sourceX, sourceY, width, height) {
    if (!this.loaded) { return; }

    var scale = Eg.sys.scale;
    sourceX = sourceX ? sourceX * scale : 0;
    sourceY = sourceY ? sourceY * scale : 0;
    width = (width ? width : this.width) * scale;
    height = (height ? height : this.height) * scale;

    Eg.sys.context.drawImage(
			this.data, sourceX, sourceY, width, height,
			Eg.sys.getDrawPos(targetX),
			Eg.sys.getDrawPos(targetY),
			width, height
		);

    Eg.Image.drawCount++;
  },


  drawTile: function (targetX, targetY, tile, tileWidth, tileHeight, flipX, flipY) {
    tileHeight = tileHeight ? tileHeight : tileWidth;

    if (!this.loaded || tileWidth > this.width || tileHeight > this.height) { return; }

    var scale = Eg.sys.scale;
    var tileWidthScaled = tileWidth * scale;
    var tileHeightScaled = tileHeight * scale;

    var scaleX = flipX ? -1 : 1;
    var scaleY = flipY ? -1 : 1;

    if (flipX || flipY) {
      Eg.sys.context.save();
      Eg.sys.context.scale(scaleX, scaleY);
    }
    Eg.sys.context.drawImage(
			this.data,
			(Math.floor(tile * tileWidth) % this.width) * scale,
			(Math.floor(tile * tileWidth / this.width) * tileHeight) * scale,
			tileWidthScaled,
			tileHeightScaled,
			Eg.sys.getDrawPos(targetX) * scaleX - (flipX ? tileWidthScaled : 0),
			Eg.sys.getDrawPos(targetY) * scaleY - (flipY ? tileHeightScaled : 0),
			tileWidthScaled,
			tileHeightScaled
		);
    if (flipX || flipY) {
      Eg.sys.context.restore();
    }

    Eg.Image.drawCount++;
  }
});
Eg.Image.drawCount = 0;
Eg.Image.cache = {};
Eg.Image.reloadCache = function () {
  for (path in Eg.Image.cache) {
    Eg.Image.cache[path].reload();
  }
};